import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.LinkedBlockingQueue;
import javax.swing.JOptionPane;

/**
 * Controleur de la fenêtre principale
 * 
 * @author H4201
 * 
 */
public class ControleurFenetrePrincipale implements ActionListener {
	/**
	 * Fenêtre principale
	 */
	private FenetrePrincipale fenetre;

	/**
	 * Type de pièce à produire en premier (A ou B)
	 */
	private String premierType;

	/**
	 * Type de pièce en cours de production (A ou B)
	 */
	private String enProd;

	/**
	 * Fenêtre de commande
	 */
	private FenetreCommande fenCommande;

	/**
	 * Port utilisé pour la communication avec Linux
	 */
	private int port;

	/**
	 * Ip utilisé pour la communication avec Linux
	 */
	private String ip;

	/**
	 * Boite aux lettres utilisée pour l'envoi de message
	 */
	private LinkedBlockingQueue<String> bal;

	/**
	 * Constructeur de ControleurFenetrePrincipale. Crée la boite aux lettres
	 * pour l'envoi de message, la fenêtre d'initialisation du réseau, puis la
	 * fenêtre principale.
	 */
	public ControleurFenetrePrincipale() {
		bal = new LinkedBlockingQueue<String>();
		new FenetreInitReseau(this);
		fenetre = new FenetrePrincipale(this);
	}

	/**
	 * Détecte l'élément posant problème à l'aide du numéro d'erreur passé en
	 * paramètre. Passe le voyant de l'élément en rouge. Grise les boutons
	 * "Arrêt", "Arrêt lot" et rend le bouton "Erreur Reparées" cliquable.
	 * 
	 * @param numErreur
	 *            Numéro de l'erreur
	 */
	public void addErreur(int numErreur) {
		fenetre.setBArretEnable(false);
		fenetre.setBArretLotEnable(false);
		fenetre.setBErreursRepareesEnable(true);
		fenetre.getErreur(numErreur).setBackground(Color.RED);
	}

	/**
	 * Affiche le message passé en paramètre dans le champ de log.
	 * 
	 * @param string
	 *            Message à afficher
	 */
	public void addLog(String string) {
		fenetre.addLog(string);
	}

	/**
	 * Gère les clics sur les boutons Bouton d'arrêt : envoie le message "103"
	 * Bouton d'arrêt de lot : envoie le message "115" Bouton "Erreurs réparées"
	 * : envoie le message "112" Bouton Quitter : arrête WindowsEnvoi. Dans le
	 * main, conduit à la fermeture de l'application. Bouton Commande : Ouvre
	 * une fenêtre de type FenetreCommande
	 */
	@Override
	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource() == fenetre.getbArret()) {
			envoi("103");
		} else if (arg0.getSource() == fenetre.getbArretLotEnCours()) {
			envoi("115");
		} else if (arg0.getSource() == fenetre.getbErreursReparees()) {
			clearErreurs();
			envoi("112");
		} else if (arg0.getSource() == fenetre.getbQuitter()) {
			WindowsEnvoi.arret();
		} else if (arg0.getSource() == fenetre.getbCommande()) {
			fenCommande = new FenetreCommande(this);
		}
	}

	/**
	 * Repasse tous les voyants de statut à vert. Grise le bouton
	 * "Erreurs réparées", rend les boutons "Arrêt" et "Arrêt lot" cliquables
	 */
	private void clearErreurs() {
		for (int i = 0; i < 8; i++) {
			fenetre.getErreur(i).setBackground(Color.GREEN);
			fenetre.setBErreursRepareesEnable(false);
			fenetre.setBArretEnable(true);
			fenetre.setBArretLotEnable(true);
		}
	}

	/**
	 * Envoie un message pour lancer la production. Rend les boutons "Arrêt" et
	 * "Commande" cliquables.
	 */
	public void lancementProduction() {
		envoi("102 " + premierType);
		enProd = premierType;
		fenetre.getbArret().setEnabled(true);
		fenetre.getbCommande().setEnabled(true);
	}

	/**
	 * Spécifie l'attribut premierType, correspondant au type de pièce à
	 * produire en premier
	 * 
	 * @param typeAProduire
	 *            Type de pièce à produire
	 */
	public void setPremierType(String typeAProduire) {
		premierType = typeAProduire;
	}

	/**
	 * Informe la FenetreCommande d'une erreur de retrait
	 */
	public void erreurRetrait() {
		fenCommande.erreurRetrait();
	}

	/**
	 * Informe la FenetreCommande que le retrait a été réussi
	 * 
	 * @param string
	 *            Détails de la commande réussie
	 */
	public void retraitReussi(String string) {
		fenCommande.retraitReussi(string);
	}

	/**
	 * Spécifie l'ip et le port utilisés dans la communication entre Windows et
	 * Linux
	 * 
	 * @param ip2
	 *            Ip
	 * @param port2
	 *            Port
	 */
	public void setIpPort(String ip2, int port2) {
		ip = ip2;
		port = port2;
	}

	/**
	 * Renvoie l'ip
	 * 
	 * @return Ip utilisé dans la communication entre Windows et Linux
	 */
	public String getIp() {
		return ip;
	}

	/**
	 * Revoie le port
	 * 
	 * @return Port utilisé dans la communication entre Windows et Linux
	 */
	public int getPort() {
		return port;
	}

	/**
	 * Renvoie la boite au lettre utilsée par le thread d'envoi
	 * 
	 * @return Boite aux lettres utilisée par le thread d'envoi
	 */
	public LinkedBlockingQueue<String> getBal() {
		return bal;
	}

	/**
	 * Place le message passé en paramètre dans la boite aux lettres d'envoi
	 * 
	 * @param string
	 *            Message à envoyer
	 */
	public void envoi(String string) {
		try {
			bal.put(string);
		} catch (InterruptedException e) {
			JOptionPane.showMessageDialog(null,
					"Erreur : Le message suivant n'a pas pu être envoyé :"
							+ string, "Erreur envoi", JOptionPane.OK_OPTION);
			e.printStackTrace();
		}
	}

	/**
	 * Si le lot terminé correspond au type de pièce produit en premier, propose
	 * à l'utilisateur de lancer la production du deuxième lot. Si l'utilisateur
	 * accepte, lance la production. Sinon, les seules actions dorénavant
	 * autorisées sont les commandes et l'arrêt de l'application.
	 */
	public void finLot() {
		int productionArretee = JOptionPane.NO_OPTION;
		if (enProd.equals(premierType)) {
			productionArretee = JOptionPane.showConfirmDialog(null,
					"Souhaitez-vous passer au lot suivant ?",
					"Changement de lot", JOptionPane.YES_NO_OPTION);
		}
		if (productionArretee == JOptionPane.NO_OPTION) {
			fenetre.getbArret().setEnabled(true);
			fenetre.getbArretLotEnCours().setEnabled(false);
			fenetre.getbErreursReparees().setEnabled(false);
		} else {
			String nouveauType = "0";
			if (nouveauType.equals(premierType)) {
				nouveauType = "1";
			}
			enProd = nouveauType;
			envoi("102 " + nouveauType);
		}
	}

	/**
	 * Convertit un string correspondant au type de pièce (0 ou 1) en A ou B
	 * 
	 * @param entier
	 *            "0" ou "1"
	 * @return "A" si on a passé "0" en paramètre, "B" sinon
	 */
	public String intToType(String entier) {
		if (entier.equals("0")) {
			return "A";
		}
		return "B";
	}

	/**
	 * Transmet le message d'arrêt à la fenêtre principale
	 */
	public void arret() {
		fenetre.arret();
	}

	/**
	 * Ferme les fenêtres.
	 */
	public void finAppli() {
		if (fenCommande != null) {
			fenCommande.dispose();
		}
		fenetre.dispose();
	}

	/**
	 * Crée une fenêtre de reprise, permettant à l'utilisateur de choisir les
	 * actions à faire.
	 */
	public void erreurReparees() {
		new FenetreReprise(this);
	}

}
